package mqtt

import (
	"encoding/json"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"longmen/server/config/global"
	footballSrv "longmen/server/internal/services/nami/services/sports/football"
	fbcache2 "longmen/server/internal/services/nami/services/sports/football/fbcache"
	"longmen/server/internal/services/nami/utils"
	"longmen/server/pkg/db/mysql/models/models_sports"
	"strings"
)

const footBallTopicName = "sports/football/match.v5"

type (
	FootBallMQ struct {
	}
	FootBallScores []interface{}
	Stats          struct {
		Type int `json:"type"`
		Home int `json:"home"`
		Away int `json:"away"`
	}
	FootBallResponse struct {
		ID        int            `json:"id"`
		Score     FootBallScores `json:"score"`
		Stats     []Stats        `json:"stats"`
		Incidents []struct {
			Type     int `json:"type"`
			Position int `json:"position"`
			Time     int `json:"time"`
			Second   int `json:"second"`
		} `json:"incidents"`
		Tlive []Tlive `json:"tlive"`
	}
	Tlive struct {
		Time     string `json:"time"`
		Type     int    `json:"type"`
		Data     string `json:"data"`
		Position int    `json:"position"`
		Main     int    `json:"main"`
	}
)

// GetUpdate 比分数据 TO Mysql
func (s FootBallScores) GetUpdate() models_sports.FootballMatch {
	if len(s) < 4 {
		return models_sports.FootballMatch{}
	}
	homeScores, _ := json.Marshal(s[2])
	awayScores, _ := json.Marshal(s[3])
	global.Log.Debugf("更新足球数据，homeScores:%v,awayScores:%v,TimePlayed:%v,ID:%v", string(homeScores), string(awayScores), s.GetTimePlayed(int64(s[4].(float64)), int(s[1].(float64))), int(s[0].(float64)))
	return models_sports.FootballMatch{
		ID:         int(s[0].(float64)),
		StatusID:   models_sports.FootBallMatchStatus(s[1].(float64)),
		HomeScores: string(homeScores),
		AwayScores: string(awayScores),
		TimePlayed: s.GetTimePlayed(int64(s[4].(float64)), int(s[1].(float64))),
	}
}
func (s FootBallScores) GetTimePlayed(kTime int64, matchStatus int) uint32 {
	return models_sports.FootBallMatchStatus(matchStatus).GetTimePlayed(kTime)
}

// GetScore 比分数据
func (s FootBallScores) GetScore() fbcache2.Score {
	if len(s) < 4 {
		return fbcache2.Score{}
	}
	homeItem := s[2].([]interface{})
	awayItem := s[3].([]interface{})
	return fbcache2.Score{
		MatchId:     int(s[0].(float64)),
		MatchStatus: int(s[1].(float64)),
		HomeScore: fbcache2.ScoreItem{
			Score:        utils.GetInt(homeItem[0]),
			HalfScore:    utils.GetInt(homeItem[1]),
			RedCard:      utils.GetInt(homeItem[2]),
			YellowCard:   utils.GetInt(homeItem[3]),
			CornerKick:   utils.GetInt(homeItem[4]),
			OTScore:      utils.GetInt(homeItem[5]),
			PenaltyScore: utils.GetInt(homeItem[6]),
		},
		AwayScore: fbcache2.ScoreItem{
			Score:        utils.GetInt(awayItem[0]),
			HalfScore:    utils.GetInt(awayItem[1]),
			RedCard:      utils.GetInt(awayItem[2]),
			YellowCard:   utils.GetInt(awayItem[3]),
			CornerKick:   utils.GetInt(awayItem[4]),
			OTScore:      utils.GetInt(awayItem[5]),
			PenaltyScore: utils.GetInt(awayItem[6]),
		},
		KickOutTime: int64(s[4].(float64)),
		TimePlayed:  s.GetTimePlayed(int64(s[4].(float64)), int(s[1].(float64))),
	}
}

func (f *FootBallMQ) InitTopic(client mqtt.Client) {
	token := client.Subscribe(footBallTopicName, 1, f.MessageHandler)
	token.Wait()
	global.Log.Info("init topic 足球：", footBallTopicName)
}

func (f *FootBallMQ) MessageHandler(client mqtt.Client, msg mqtt.Message) {
	err := f.Exec(msg.Payload(), msg.MessageID())
	if err != nil {
		global.Log.Error("消息处理失败通知保留：", err)
		msg.Retained()
		return
	}
	msg.Ack()
}

func (f *FootBallMQ) Exec(body []byte, MessageID uint16) error {
	global.Log.Info("football receive: ", string(body))
	records := make([]FootBallResponse, 0)
	err := json.Unmarshal(body, &records)
	if err != nil {
		global.Log.Error("反序列化足球数据失败：", err)
		return err
	}
	err = f.publishTextLive(records)
	if err != nil {
		return err
	}

	err = f.publishScores(records)
	if err != nil {
		return err
	}
	err = f.publishStats(records)
	if err != nil {
		return err
	}
	return nil
}

func (f *FootBallMQ) Quit(client mqtt.Client) {
	client.Unsubscribe(footBallTopicName)
}

// publishStats 即时技术统计
func (f *FootBallMQ) publishStats(records []FootBallResponse) error {
	res := make([]fbcache2.NatsStats, 0)
	for _, record := range records {
		for _, stat := range record.Stats {
			res = append(res, fbcache2.NatsStats{
				MatchId: record.ID,
				Type:    stat.Type,
				Home:    stat.Home,
				Away:    stat.Away,
			})
		}
	}
	if len(res) > 0 {
		err := fbcache2.NewStatsCache().PublishStats(res)
		if err != nil {
			global.Log.Error("stats publish error: ", err)
			return err
		}
	}
	return nil
}

// publishScores 实时比分更新
func (f *FootBallMQ) publishScores(records []FootBallResponse) error {
	updateInterfaces := make([]footballSrv.UpdateMatchInterface, 0)
	pubs := make([]fbcache2.PublishScoreInterface, 0)
	for _, record := range records {
		updateInterfaces = append(updateInterfaces, record.Score)
		pubs = append(pubs, record.Score)
	}
	if len(updateInterfaces) > 0 {
		footballSrv.UpdateMatchScore(updateInterfaces)

	}
	if len(pubs) > 0 {
		err := fbcache2.NewScoreRedis().PublishLiveScore(pubs)
		if err != nil {
			global.Log.Error("推送nat数据失败", err)
			return err
		}
	}
	return nil
}

// publishTextLive 文字直播数据推送
func (f *FootBallMQ) publishTextLive(records []FootBallResponse) error {
	for _, record := range records {
		textLive := make([]fbcache2.TextLive, 0)
		for _, t := range record.Tlive {
			var rawText string
			// 去除时间的文本
			textHadTime := strings.Index(t.Data, "'")
			if textHadTime == -1 {
				rawText = t.Data
			} else {
				index := strings.Index(t.Data, "-")
				if index == -1 {
					rawText = t.Data
				} else {
					rawText = strings.TrimSpace(t.Data[index+1:])
				}
				textLive = append(textLive, fbcache2.TextLive{
					MatchId:  record.ID,
					Time:     t.Time,
					Type:     t.Type,
					Data:     rawText,
					Position: t.Position,
					Main:     t.Main,
				})
			}

		}
		if len(textLive) == 0 {
			return nil
		}
		err := fbcache2.NewTextLiveCache().PublishTextLive(textLive)
		if err != nil {
			global.Log.Error("发布订阅数据失败：", err)
			return err
		}
	}
	return nil
}
